import { _decorator, Color, Component, instantiate, Node, Prefab, Vec2, Vec3 } from 'cc';
import { Tools } from '../../Util/Tools';
import { UnitPlanet } from '../UnitPlanet';
import AssetsMgr from '../../Model/AssetsMgr';
import { ISpawnerEventCall, SpawnerCom, SpawnEvent } from './SpawnerCom';
import { Global, TechnologyType, UnitType } from '../../Util/Global';
import { Unit } from '../Unit';
import { Bullet_2 } from '../Bullet_2';
import { UICtrl } from '../../Ctrl/UICtrl';
import { EconomicCom } from './EconomicCom';
import { FactoryCom } from './FactoryCom';
import GameEventMgr, { GameEvent } from '../../Model/GameEventMgr';
const { ccclass, property } = _decorator;

@ccclass('EarthCannonCom')
export class EarthCannonCom extends Component {

    @property(UnitPlanet)
    public planet: UnitPlanet = null;
    //最大拥有大炮数量
    @property
    public cannonMaxCount: number = 10;
    //每个大炮攻击角度范围
    @property
    public cannonAttackAngle: number = 90;

    public bulletCost: number = 1;
    //攻击距离
    public attackDis: number = 400;

    protected cannon_prefab: Prefab = null;
    protected cannon: Node[] = [];//大炮节点
    protected cannon_arsenal: SpawnerCom[] = [];//大炮子弹孵化组件
    protected cannon_aim: Unit[] = [];//当前帧瞄准目标
    protected cannonMiniRadianInterval: number = 0;

    protected cannonAttackRadian: number = 0;
    protected planetEconmic: EconomicCom = null;
    protected planetFactory: FactoryCom = null;

    onEnable() {
        // 计算最小间隔弧度
        this.cannonMiniRadianInterval = 2 * Math.PI / this.cannonMaxCount;

        this.cannon_prefab = AssetsMgr.prefabMap.get('EarthCannon');

        this.cannonAttackRadian = this.cannonAttackAngle / 180 * Math.PI;

        // this.addCannon();
        // this.addCannon();
        // this.addCannon();

        GameEventMgr.Register(this, GameEvent.EconomicComBroken, (unit: UnitPlanet) => {
            if (this.planet == unit) {
                this.planet = null;
            }
        });
    }

    protected onDisable(): void {
        this.cannon.forEach((ca) => {
            ca.destroy();
        });
        this.cannon = [];
        this.cannon_arsenal = [];
        this.cannon_aim = [];
        this.bulletCost = 1;
        this.attackDis = 400;
    }

    addCannon() {
        if (!this.planet || !this.cannon_prefab) {
            console.warn("Planet or cannon prefab is not set!");
            return;
        }
        this.planetEconmic = this.planet.getComponent(EconomicCom);
        this.planetFactory = this.planet.getComponent(FactoryCom);

        let radius = this.planet.collider.radius; // 圆的半径

        if (this.cannon.length >= this.cannonMaxCount) {
            console.warn("Cannot add more cannons. Maximum cannon limit reached!");
            return;
        }

        // 如果当前没有任何大炮，直接放置第一个大炮
        if (this.cannon.length === 0) {
            // let angle = 0; // 起始角度为 90 度
            let angle = Tools.getRandomInt(0, 360);

            this.placeCannonAtAngle(angle, radius);
            // console.log("Added first cannon at angle 0 degrees.");
            return;
        }

        // 遍历所有现有大炮，寻找可以放置新大炮的间隔
        let angles = this.cannon.map(cannonNode => cannonNode.angle).sort((a, b) => a - b); // 按角度排序
        let foundPosition = false;
        let miniAngle = this.cannonMiniRadianInterval * (180 / Math.PI) * 2;

        for (let i = 0; i < angles.length; i++) {
            let currentAngle = angles[i];
            let nextAngle = angles[(i + 1) % angles.length]; // 环状考虑

            // 计算角度差
            let angleDifference = nextAngle > currentAngle
                ? nextAngle - currentAngle
                : 360 - (currentAngle - nextAngle); // 最短弧长


            if (angleDifference >= miniAngle) {
                // let newAngle = currentAngle + angleDifference / 2;

                let newAngle = currentAngle + Tools.getRandomInt(miniAngle, angleDifference - miniAngle);
                if (newAngle >= 360) {
                    newAngle -= 360; // 保证角度在 [0, 360)
                }
                this.placeCannonAtAngle(newAngle, radius);
                // console.log("Added cannon between angles:", currentAngle, "and", nextAngle);
                foundPosition = true;
                break;
            }
        }

        // 如果没有找到合适的间隔，重新排列所有大炮
        if (!foundPosition) {
            // console.log("No suitable position found. Rearranging all cannons...");
            this.placeCannonAtAngle(0, radius);
            this.rearrangeCannons();
        }
    }

    protected placeCannonAtAngle(angle: number, radius: number) {
        let cannonNode = instantiate(this.cannon_prefab);
        let radian = angle * (Math.PI / 180); // 转换为弧度
        let x = radius * Math.cos(radian);
        let y = radius * Math.sin(radian);
        cannonNode.setPosition(x, y, 0);
        cannonNode.angle = angle; // 保存角度信息
        this.node.addChild(cannonNode);
        this.cannon.push(cannonNode);

        //初始化炮弹
        let arsenal = cannonNode.addComponent(SpawnerCom);
        arsenal.AddProduct(AssetsMgr.getUnitPrefab(UnitType.Bullet, 'Bullet4'));
        this.cannon_arsenal.push(arsenal);
        this.cannon_aim.push(null);

        let self = this;
        let call: ISpawnerEventCall = {
            SpawnEventCallback(unit: Unit, event: SpawnEvent) {
                if (event != SpawnEvent.SPAWNING) {
                    return true
                }
                let bullet = <Bullet_2>unit;

                let c_wp = cannonNode.getWorldPosition();
                bullet.node.setWorldPosition(c_wp);
                let target = self.cannon_aim[self.cannon.indexOf(cannonNode)];
                if (target && !target.death) {
                    let v = target.unitWorldPos;
                    self.CalculateAimingDir(target, 30, v);
                    bullet.moveVec.set(v.x, v.y);
                }
                else {
                    bullet.moveVec.set(cannonNode.position.x, cannonNode.position.y);
                }

                bullet.parentUnit = self.planet;//设置工厂作为父级
                self.planetEconmic.CostRes(self.bulletCost);
                return false;
            },
        }
        arsenal.onSpawnEventCallback('EarthCannonHandle', call);
    }

    protected rearrangeCannons() {
        let radius = this.planet.collider.radius; // 圆的半径
        let angleStep = 360 / (this.cannon.length); // 计算间隔角度

        for (let i = 0; i < this.cannon.length; i++) {
            let angle = i * angleStep; // 顺序排列，起始角度为 0
            let radian = angle * (Math.PI / 180); // 转换为弧度

            let cannonNode = this.cannon[i];
            let x = radius * Math.cos(radian);
            let y = radius * Math.sin(radian);
            cannonNode.setPosition(x, y, 0);
            cannonNode.angle = angle; // 更新角度信息
        }

        // console.log("Rearranged all cannons with equal spacing.");
    }

    private _targetWorldDir: Vec3 = new Vec3();
    private _targetWorldDir_v2: Vec2 = new Vec2();
    /** 计算瞄准方向，根据提供的子弹速度和目标的速度预测撞击位置
     * @param selfSpeed 提供参与计算的子弹速度
     */
    CalculateAimingDir(target: Unit, selfSpeed: number, out?: Vec2 | Vec3) {

        if (!this.planet || this.planet.death) {
            return;
        }

        target.node.getWorldPosition(this._targetWorldDir);
        let targetV = target.rigBody.linearVelocity.normalize();
        let dis = this.planet.DistanceOther(target);
        //近似计算
        let time = dis / selfSpeed;

        //公式计算 物理速度和坐标单位应该有5倍差 
        //即dis应该除5，target.speed再乘5，相当于没变，于是这个差不用管
        // let dr = this.planet.GetDirToOther(target);
        // let d = 2 * (targetV.x * dr.x + targetV.y * dr.y);
        // let time = dis + d * d / selfSpeed / selfSpeed / 4;
        // time = Math.sqrt(time) + d / dis / 2;

        targetV.multiplyScalar(time * target.speed);
        this._targetWorldDir.x += targetV.x;
        this._targetWorldDir.y += targetV.y;
        this._targetWorldDir.subtract(this.planet.unitWorldPos);//向量减法会改变自身

        this._targetWorldDir_v2.set(this._targetWorldDir.x, this._targetWorldDir.y);
        if (out) {
            out.set(this._targetWorldDir.x, this._targetWorldDir.y);
        }
    }

    private cv = new Vec2;

    protected lateUpdate(dt: number): void {

        if (Global.gameManager.pause || !this.planet || this.planet.death || !this.cannon_prefab) {
            return;
        }
        if (this.planet.enemyCount <= 0) {
            return;
        }
        let enemys = this.planet.GetEnemyArr();
        if (enemys.length <= 0) {
            return;
        }

        let res = this.planetEconmic.mine_res;

        for (let i = 0; i < this.cannon.length; i++) {
            this.cv.set(this.cannon[i].position.x, this.cannon[i].position.y);
            let aimColor = Color.GRAY;
            let ca = this.cannon_arsenal[i];
            if (res - this.bulletCost > 0) {
                for (let j = 0; j < enemys.length; j++) {
                    let ev = enemys[j].unitWorldPos_v2.subtract(this.planet.unitWorldPos_v2);
                    let radian = this.cv.signAngle(ev);
                    let abs_radian = Math.abs(radian);
                    if (this.planet.DistanceOther(enemys[j]) < this.attackDis
                        && abs_radian < this.cannonAttackRadian / 2) {
                        this.cannon_aim[i] = enemys[j];
                        ca.StartIdleWorkShop();
                        this.CalculateAimingDir(this.cannon_aim[i], 30);
                        let aim_radian = this.cv.signAngle(this._targetWorldDir_v2);

                        this.cannon[i].children[0].setRotationFromEuler(0, 0, aim_radian * 180 / Math.PI)
                        aimColor = Color.RED;
                        break;
                    }
                }
            }

            if (this.planet.playerCtrl
                && Global.gameManager.playerData.technologyProduct.get(TechnologyType.PlanetWarning) > 0) {

                let v1 = this.cv.clone().rotate(-this.cannonAttackRadian / 2);
                let v2 = this.cv.clone().rotate(this.cannonAttackRadian / 2);
                UICtrl.FanShapeRenderer(this.planet.unitWorldPos, v1, v2,
                    this.attackDis / Global.CameraOrthoScale, aimColor);

            }
        }
    }
}


